package service

import (
	"encoding/json"
	"fmt"
	"gitee/com.xiaoxin/go-send/model"
	"gitee/com.xiaoxin/go-send/store"
	"strconv"
	"sync"
)

type ApiService interface {
	TreeList() []model.TreeNode
	SaveOrUpdateDirectory(directory model.ApiDirectory)
	SaveOrUpdateInstance(api model.Api)
	DeleteDirectory(directoryId int)
	DeleteInstance(instanceId int)
}

var (
	_       ApiService = (*apiService)(nil)
	api     ApiService
	apiOnce sync.Once
)

type apiService struct {
	store *store.ApiStore
}

func NewApiService() ApiService {
	apiOnce.Do(func() {
		api = &apiService{
			store: store.GetSqlite().NewApiStore(),
		}
	})
	return api
}

func (service *apiService) TreeList() []model.TreeNode {
	var result []model.TreeNode = make([]model.TreeNode, 0)
	directoryIdMap := make(map[string]*model.TreeNode)
	directoryList := service.store.GetDirectoryList()
	fmt.Printf("directory list %+v\n", directoryList)
	for _, directory := range directoryList {
		treeNode := model.TreeNode{
			Id:       directory.DirectoryId,
			Label:    directory.DirectoryName,
			ParentId: strconv.Itoa(directory.ParentId),
			Type:     "1",
			Leaf:     false,
			Payload:  model.ApiDirectory{Id: directory.Id, Name: directory.DirectoryName, ParentId: directory.ParentId},
		}
		directoryIdMap[directory.DirectoryId] = &treeNode
	}

	instanceList := service.store.GetInstanceList()
	fmt.Printf("instace list: %+v\n", instanceList)
	for _, instance := range instanceList {
		i, _ := strconv.Atoi(instance.DirectoryId)
		requestInfo := model.RequestInfo{}
		_ = json.Unmarshal([]byte(instance.RequestInfo), &requestInfo)
		treeNode := model.TreeNode{
			Id:       instance.InstanceId,
			Label:    instance.InstanceName,
			ParentId: instance.DirectoryId,
			Type:     "2",
			Leaf:     true,
			Payload:  model.Api{Id: instance.Id, Name: instance.InstanceName, DirectoryId: i, RequestInfo: requestInfo},
		}
		if directoryIdMap[instance.DirectoryId].Children == nil {
			directoryIdMap[instance.DirectoryId].Children = make([]model.TreeNode, 0)
		}
		var children = directoryIdMap[instance.DirectoryId].Children
		directoryIdMap[instance.DirectoryId].Children = append(children, treeNode)
	}

	for _, treeNode := range directoryIdMap {
		if directoryIdMap[treeNode.ParentId] != nil {
			directoryIdMap[treeNode.ParentId].Children = append(directoryIdMap[treeNode.ParentId].Children, *treeNode)
		}
	}
	if directoryIdMap["1"] != nil {
		result = directoryIdMap["1"].Children
	}
	return result
}

func (service *apiService) SaveOrUpdateDirectory(directory model.ApiDirectory) {
	id := directory.Id
	if id == 0 {
		// 新增
		id = service.store.DirectoryIndex()
		directory.Id = id
	}
	directoryId := strconv.Itoa(id)
	service.store.SaveOrUpdateDirectory(store.DirectoryEntity{
		Id:            id,
		DirectoryId:   directoryId,
		DirectoryName: directory.Name,
		ParentId:      directory.ParentId,
	})
}

func (service *apiService) SaveOrUpdateInstance(api model.Api) {
	marshal, err := json.Marshal(api.RequestInfo)
	if err != nil {
		return
	}
	if api.Id == 0 {
		api.Id = service.store.InstanceIndex()
	}
	instanceId := strconv.Itoa(api.Id)
	service.store.SaveOrUpdateInstance(store.InstanceEntity{
		Id:           api.Id,
		DirectoryId:  strconv.Itoa(api.DirectoryId),
		InstanceId:   instanceId,
		InstanceName: api.Name,
		RequestInfo:  string(marshal),
	})
}

func (service *apiService) DeleteDirectory(directoryId int) {
	service.store.DeleteDirectory(directoryId)
}

func (service *apiService) DeleteInstance(instanceId int) {
	service.store.DeleteInstance(instanceId)
}
